<template>
  <div>
    <!-- 商品分类选项 -->
    <el-card style="margin-bottom: 20px">
      <CategorySelector @changeCategoryId="changeCategoryId" ref="cs"/>
    </el-card>
    <!-- 商品分类列表 -->
    <el-card>
      <!-- 平台属性及列表数据界面 -->
      <div v-show="!isshowAddOrUpdateAttr">
        <!-- 添加按钮 -->
        <el-button
          type="primary"
          icon="el-icon-plus"
          style="margin-bottom: 20px"
          @click="showAddAttr"
          :disabled="!category3Id"
          >添加</el-button
        >
        <!-- 商品分类表格 -->
        <el-table
          :data="attrList"
          border
          style="width: 100%"
          v-loading="loading"
        >
          <el-table-column type="index" label="序号" width="80" align="center">
          </el-table-column>
          <el-table-column prop="attrName" label="属性名称" width="150">
          </el-table-column>
          <el-table-column label="属性值列表">
            <template slot-scope="{ row }">
              <!-- 遍历平台属性对象的attrValueList数组 -->
              <el-tag v-for="(val, index) in row.attrValueList" :key="val.id">{{
                val.valueName
              }}</el-tag>
            </template>
          </el-table-column>
          <el-table-column label="操作" width="150">
            <template slot-scope="{ row }">
              <!-- 引入提示信息按钮组件，设置提示内容  FIXME: 注意组件间的传参-->
              <HintButton
                title="修改属性"
                size="mini"
                type="primary"
                icon="el-icon-edit"
                @click="showUpdateAttr(row)"
              ></HintButton>
              <el-popconfirm
                :title="`您确定要删除${row.attrName}吗?`"
                @onConfirm="deleteAttr(row.id)"
              >
                <!-- 引入文字提示按钮的组件 -->
                <HintButton
                  title="删除属性"
                  size="mini"
                  type="danger"
                  icon="el-icon-delete"
                  slot="reference"
                ></HintButton>
              </el-popconfirm>

              <!-- <el-button
                size="mini"
                type="primary"
                icon="el-icon-edit"
                @click="showUpdateAttr"
              ></el-button>
              <el-button
                size="mini"
                type="danger"
                icon="el-icon-delete"
              ></el-button> -->
            </template>
          </el-table-column>
        </el-table>
      </div>
      <!-- 添加|修改平台属性及值页面 -->
      <div v-show="isshowAddOrUpdateAttr">
        <!-- FIXME: TODO: 项目之解决平台属性失去焦点的bug---我也不知道解决了什么
        操作步骤:1.el-form只包含属性名称,不包含表格; 2.由于el-form 和表格都涉及到formData,把el-form中的删除即可????????? -->
        <el-form inline>
          <!-- 属性名称 -->
          <el-form-item label="属性名称">
            <el-input
              type="text"
              v-model="formData.attrName"
              placeholder="请输入属性值名称"
            ></el-input>
          </el-form-item>
        </el-form>
        <!-- 两个按钮 -->
        <div style="margin-bottom: 20px">
          <el-button type="primary" icon="el-icon-plus" @click="addAttrValue" :disabled="!formData.attrName.trim().length"
            >添加属性值</el-button
          >
          <el-button @click="isshowAddOrUpdateAttr = false">取消</el-button>
        </div>
        <!-- 表格 -->
        <el-table :data="formData.attrValueList" border style="width: 100%">
          <el-table-column type="index" label="序号" width="80" align="center">
          </el-table-column>
          <el-table-column label="属性值名称">
            <template slot-scope="{ row, $index }">
              <!-- 通过每一行的对象的edit属性作为标识，如果true则显示文本框，否则显示span内容 -->
              <el-input
                type="text"
                v-if="row.edit"
                v-model="row.valueName"
                placeholder="请输入属性值"
                :ref="$index"
                size="mini"
                @blur="toView(row)"
                @keyup.native.enter="toView(row)"
              ></el-input>
              <span
                v-else
                @click="toEdit(row, $index)"
                style="width: 100%; display: inline-block"
                >{{ row.valueName }}</span
              >
            </template>
          </el-table-column>
          <el-table-column label="操作">
            <template slot-scope="{ row, $index }">
              <el-popconfirm
                :title="`您确定要删除${row.valueName}吗?`"
                @onConfirm="deleteValue($index)"
              >
                <!-- 引入文字提示按钮的组件 -->
                <HintButton
                  title="删除属性值"
                  size="mini"
                  type="danger"
                  icon="el-icon-delete"
                  slot="reference"
                ></HintButton>
                <!-- <el-button
                  size="mini"
                  type="danger"
                  icon="el-icon-delete"
                ></el-button> -->
              </el-popconfirm>
            </template>
          </el-table-column>
        </el-table>
        <!-- 两个按钮 -->
        <div style="margin-top: 20px">
          <el-button type="primary" @click="save" :disabled="!isSaveValid">保存</el-button>
          <el-button @click="isshowAddOrUpdateAttr = false">取消</el-button>
        </div>
      </div>
    </el-card>
  </div>
</template>

<script>
// FIXME: 引入深拷贝
import cloneDeep from "lodash/cloneDeep";
export default {
  name: "Attr",
  data() {
    return {
      category1Id: "", //一级分类的id
      category2Id: "", //二级分类的id
      category3Id: "", //三级分类的id
      attrList: [], //平台属性的数组数据
      isshowAddOrUpdateAttr: false, //用来控制添加|修改平台属性值的界面的标识
      loading: false, //加载数据效果的标识
      // 存储平台属性对象的
      formData: {
        attrName: "",
        attrValueList: [],
      },
    };
  },
  methods: {
    // 选中的分类内容改变的时候分发的自定义事件对应的回调函数
    changeCategoryId({ level, categoryId }) {
      if (level === 1) {
        this.category1Id = categoryId;
        // 置空二级|三级分类的id和数组
        this.category2Id = null;
        this.category3Id = null;
        this.attrList = [];
      } else if (level === 2) {
        this.category2Id = categoryId;
        // 置空三级分类的id和数组
        this.category3Id = null;
        this.attrList = [];
      } else {
        this.category3Id = categoryId;
        this.loading = true; //获取平台属性前设置的加载效果
        // 获取平台属性数据
        this.getAttrList();
      }
    },
    // 获取平台属性的数据
    async getAttrList() {
      let result = await this.$API.attr.getAttrInfoList(
        this.category1Id,
        this.category2Id,
        this.category3Id
      );
      this.loading = false; //关闭加载效果
      if (result.code == 200) {
        // 更新数组
        this.attrList = result.data;
      }
    },
    // 点击添加属性按钮，显示添加平台属性界面
    showAddAttr() {
      // 点击添加,页面不应该出现数据
      this.formData = {
        attrName: "", //属性名字
        attrValueList: [], //属性对象数组
        categoryId: this.category3Id, //三级分类的id
        categoryLevel: 3, //级别默认为3
      };
      // 显示添加平台属性界面
      this.isshowAddOrUpdateAttr = true;
    },
    // 点击修改属性按钮，显示修改平台属性界面
    showUpdateAttr(attrInfo) {
      // FIXME: 更新传入过来的属性值对象:
      // 由于两个值指向的是同一个地址值,一旦修改部分修改了数据,即使没点确定按钮,也会进行修改
      // this.formData = attrInfo;//不适用
      // 分析: 浅拷贝的话,两个对象中的方法指向同一个地址,只要输入点击取消仍会保存
      // this.formData = { ...attrInfo };//浅拷贝--不适用
      this.formData = cloneDeep(attrInfo); // 深拷贝
      // 显示修改属性的页面
      this.isshowAddOrUpdateAttr = true;
    },
    // 点击添加属性值按钮的事件的回调函数
    addAttrValue() {
      this.formData.attrValueList.push({
        // 经观察发现存储的是当前平台属性值对象所在的平台属性的对象的id
        // 且attrValueList 中的id 是由后端设置的,不需要前端设置
        attrId: this.formData.id,
        valueName: "",
        edit: true, // 用来控制当前行的内容时编辑模式还是查看模式
      });
      // 设置当前的新的一行中的文本框有焦点--默认的光标
      // FIXME: 分析:
      this.$nextTick(() => {
        this.$refs[this.formData.attrValueList.length - 1].focus();
      });
    },
    // 查看模式
    toView(attrValue) {
      // 判断文本框中是否有数据,此时没有数据,则不会编程查看模式
      // FIXME: trim方法用于删除字符串头尾的空白符
      if (attrValue.valueName.trim() === "") return;
      // 校验数据 此时有数据,但是新录入的数据和之前存在的数据不能一样
      // FIXME: filter方法返回满足条件的数组
      const isRepeat =
        this.formData.attrValueList.filter(
          (val) => val.valueName == attrValue.valueName
        ).length == 2;
      if (isRepeat) {
        // 此时说明新录入的数据和数组中已经存在的数据是一样的,这是不允许的
        this.$message.warning("您输入了重复的数据,请重新输入");
        // 清空当前的重复数据
        attrValue.valueName = "";
        return;
      }
      // 此时说明,数据存在,并且有效,变成查看模式
      attrValue.edit = false;
    },
    // 编辑模式
    toEdit(attrValue, index) {
      // 判断该行是否有edit属性,如果没有就添加一个
      if (attrValue.hasOwnProperty("edit")) {
        // 如果有该属性,更改为true,变成编辑模式
        attrValue.edit = true;
      } else {
        //  FIXME: 如果没有进行添加一个,变成编辑模式
        this.$set(attrValue, "edit", true);
      }
      // 用户体验: 出现文本框,直接锁定焦点
      this.$nextTick(() => {
        this.$refs[index].focus();
      });
    },
    // 删除某个属性值的操作
    deleteValue(index) {
      this.formData.attrValueList.splice(index, 1);
      this.$message.success("删除成功");
    },
    // 保存操作
    async save() {
      // 校验数据--属性名字是否存在
      if (this.formData.attrName.trim().length == 0) return;
      // 校验数据--属性值对象TODO:
      this.formData.attrValueList = this.formData.attrValueList.filter(
        (attrValue) => {
          // TODO: delete 移除编辑或者查看模式的标识
          delete attrValue.edit;
          // TODO: !! 如果属性值为空,直接返回
          // !! 直接就是布尔类型的值
          return !!attrValue.valueName.trim();
          // return attrValue.valueName.trim();//FIXME: 也可以这样写,但是这是字符串隐式转换为布尔值没有上面的效率高
        }
      );
      // 判断是否有属性值
      if (this.formData.attrValueList.length == 0) {
        this.$message.warning("至少添加一个属性值");
        return;
      }
      // 调用保存的接口
      let result = await this.$API.attr.addOrUpdateAttrInfo(this.formData);
      // FIXME: 初级程序员的写法--嵌套层次多
      // if(result.code == 200){
      //   // 保存成功
      //   this.$message.success('保存成功');
      //   this.isshowAddOrUpdateAttr = false;//关闭添加或修改页面
      //   this.getAttrList();//刷新数据
      // }else{
      //   // 保存失败
      //   this.$message.error('保存失败');
      // }
      if (result.code !== 200) {
        // 保存失败
        this.$message.error("保存失败");
        return;
      }
      // 保存成功
      this.$message.success("保存成功");
      this.isshowAddOrUpdateAttr = false; //关闭添加或修改页面
      this.getAttrList(); //刷新数据
    },
    // 删除平台属性的操作
    async deleteAttr(attrId) {
      let result = await this.$API.attr.deleteAttrInfoById(attrId);
      if (result.code !== 200) {
        // 删除失败
        this.$message.error("删除失败");
        return;
      }
      // 删除成功
      this.$message.success("删除成功");
      // 刷新页面
      this.getAttrList();
    },
  },
  watch:{
    // 监视平台属性值的页面是否显示,显示则禁用商品分类的选项
    isshowAddOrUpdateAttr(val){
      // 添加或修改平台属性页面的标识
      this.$refs.cs.isDisabled = val;
    }
  },
  computed:{
    isSaveValid(){
      // 属性名字和属性对象是否有值
      return this.formData.attrName.trim() && this.formData.attrValueList.some(attr=>attr.valueName.trim())
    },
  }
};
</script>

<style scoped>
</style>